﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Reflection;
using System.Xml;
using System.Text.RegularExpressions;
using Newtonsoft.Json.Linq;
using System.Data.Objects;
using System.Web.Security;

using CooWork.Models;
using Coowork.Data.Mapping;

namespace CooWork.Services
{
    public class CompareDiff:ICompareDiff
    {

        public void CopyNonNullProperties(object source, object target)
        {
            // You could potentially relax this, e.g. making sure that the
            // target was a subtype of the source.
            if (source.GetType() != target.GetType() && source.GetType() != target.GetType().BaseType)
            {               
                throw new ArgumentException("Objects must be of the same type");
            }

            foreach (var prop in source.GetType()
                                       .GetProperties(BindingFlags.Instance |
                                                      BindingFlags.Public)
                                       .Where(p => !p.GetIndexParameters().Any())
                                       .Where(p => p.CanRead && p.CanWrite).Where(p => !p.GetGetMethod().IsVirtual))
            {
                var value = prop.GetValue(source, null);
                if (value != null)
                {
                    prop.SetValue(target, value, null);
                }
            }
        }


        public int CopyLogDataChanges(object source,object target)
        {
            // You could potentially relax this, e.g. making sure that the
            // target was a subtype of the source.
            if (source.GetType() != target.GetType() && source.GetType() != target.GetType().BaseType)
            {
                throw new ArgumentException("Objects must be of the same type");
            }

            var x = ObjectContext.GetObjectType(source.GetType());
            XmlNode node = Config.GetNode(x.ToString());
   
            List<string> list = new List<string>();
            foreach (XmlNode n in node.ChildNodes)
            {
                if (n.NodeType == XmlNodeType.Comment)
                    continue;
                list.Add(n.Attributes["value"].Value);
            }

            string save = "";
            string c1 = "{";
            string c2 = "{";
            int sid = 0;

            foreach (var prop in source.GetType()
                                     .GetProperties(BindingFlags.Instance |
                                                    BindingFlags.Public)
                                     .Where(p => !p.GetIndexParameters().Any())
                                     .Where(p => p.CanRead && p.CanWrite).Where(p => !p.GetGetMethod().IsVirtual))
            {
                string vname = Regex.Replace(prop.Name, @"^.*<|>.+$", "", RegexOptions.IgnoreCase);

             

                object o1 = prop.GetValue(source, null);
                if (vname.ToLower() == "id")
                {
                    int.TryParse(o1.ToString(), out sid);
                    continue;
                }
                object o2 = prop.GetValue(target, null);               
                if (o1 != null)
                {
                    prop.SetValue(target, o1, null);
                }
                if (o1 == null && o2 == null)
                    continue;

                if (list.Contains(vname) && ((o1 != null && o2 == null) || o1!=null&&!o1.Equals(o2)))
                {
                    c1 += @"""" + vname + @""":""" + (o1 == null ? "" : o1.ToString()) + @""",";
                    c2 += @"""" + vname + @""":""" + (o2 == null ? "" : o2.ToString()) + @""",";
                }
            }


            c1 = c1.Trim(',') + "}";
            c2 = c2.Trim(',') + "}";
            if (c1.Length > 4)
            {


                save += c1 + "," + c2 + "";
                CooWorkEntities context = new CooWorkEntities();
                CooLog cl = new CooLog();
                cl.Logpattern = 1;
                cl.Logtxt = save;
                cl.LogTime = DateTime.Now;
                cl.rid = sid;
                cl.ctype = x.ToString();
                cl.cid = UserService.UcId();
                cl.Loguser = UserService.Ugid();
                context.CooLogs.Add(cl);
                context.SaveChanges();
                return cl.ID;
            }

            return 0;

        }





        public void CompareJsonAndObject<T>(string json,ref T f)
        {
           


            ///
            
            var x = ObjectContext.GetObjectType(f.GetType());

            XmlNode node = Config.GetNode(x.ToString());
            if (node == null || node.ChildNodes.Count == 0)
                return;
            List<string> list = new List<string>();
            foreach (XmlNode n in node.ChildNodes)
            {
                if (n.NodeType == XmlNodeType.Comment)
                    continue;
                list.Add(n.Attributes["value"].Value);
            }

            string save = "";
            string c1 = "{";
            string c2 = "{";

            dynamic dcootask = JValue.Parse(json);
            Dictionary<string, JToken> jd = new Dictionary<string, JToken>();

            int sid=0;

            foreach (JProperty keyvalue in dcootask)
            {
                if (keyvalue.Name.ToLower() == "id")
                {
                   sid=Convert.ToInt32(System.Convert.ChangeType(keyvalue.Value, typeof(int)));
                }
                jd.Add(keyvalue.Name, keyvalue.Value);          
            }
            var finfos = x.GetFields();

            foreach (FieldInfo field in x.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly))
            {
                string vname = Regex.Replace(field.Name, @"^.*<|>.+$", "", RegexOptions.IgnoreCase);

                if (jd.ContainsKey(vname))
                {
                    object o1=field.GetValue(f);
                    object o2 = null;
                    if (!string.IsNullOrWhiteSpace(jd[vname].ToString()))
                    {
                        o2 = System.Convert.ChangeType(jd[vname], field.FieldType);
                    }
      
                  //  System.Convert.ChangeType(jd[vname], field.GetType());
                    field.SetValue(f, o2);
                    if (o1 == null && o2 == null)
                        continue;

                    if (list.Contains(vname) && ((o1 == null && o2 != null) || (o1!= null && o2 == null) || !o1.Equals(o2)))
                    {
                        c1 += @"""" + vname + @""":""" + (o1 == null ? "" : o1.ToString()) + @""",";
                        c2 += @"""" + vname + @""":""" + (o2 == null ? "" : o2.ToString()) + @""",";
                    }
                }
            }

            c1 = c1.Trim(',') + "}";
            c2 = c2.Trim(',') + "}";
            if (c1.Length > 4)
            {


                save += c1 + "," + c2 + "";
                CooWorkEntities context = new CooWorkEntities();
                CooLog cl = new CooLog();
                cl.Logpattern = 1;               
                cl.Logtxt = save;
                cl.LogTime = DateTime.Now;
                cl.rid = sid;
                cl.ctype = x.ToString();
                MembershipUser mu = Membership.GetUser();
                if (mu != null)
                {
                    cl.Loguser = (System.Guid)mu.ProviderUserKey;
                }
                context.CooLogs.Add(cl);
                context.SaveChanges();
            }
           
        }


        public void CompareAndSaveChanges(object x, object y)
        {
            Type tx = x.GetType();
            Type ty = y.GetType();

            XmlNode node = Config.GetNode(tx.ToString());
            if (node == null || node.ChildNodes.Count == 0)
                return;
            List<string> list = new List<string>();
            foreach (XmlNode n in node.ChildNodes)
            {
                if (n.NodeType == XmlNodeType.Comment)
                    continue;
                list.Add(n.Attributes["value"].Value);
            }

            if (x == null && y == null)
                return ;
            else if ((x == null && y != null) || (x != null && y == null))
                return ;
  
            string saveStr = string.Empty;
            saveStr = "{";
            //if (tx != ty)
            //    return ;
           

            foreach (FieldInfo field in tx.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly))
            {
                string vname = Regex.Replace(field.Name, @"^.*<|>.+$", "", RegexOptions.IgnoreCase);

                if (list.Contains(vname))
               {
                    if (field.FieldType.Equals(typeof(String))||field.FieldType.IsValueType)
                    {
                        string s1 = field.GetValue(x) == null ? "" : field.GetValue(x).ToString();
                        string s2 = field.GetValue(y) == null ? "" : field.GetValue(y).ToString();

                        if (s1 != s2)
                        {
                            saveStr += @""""+vname+@""":"""+s1+" - "+s2 +@""",";                           
                        }                       
                    }
               }
            }

            saveStr = saveStr.Trim(',');
            saveStr += " }";

            if (saveStr.Length > 4)
            {
               CooWorkEntities context = new CooWorkEntities();
               CooLog cl=new CooLog();
               cl.Logpattern = 1;
               cl.Logtxt = saveStr;
               cl.LogTime = DateTime.Now;
               context.CooLogs.Add(cl);
               context.SaveChanges();
            }
            
            return ;



        }
    }
}